package main

import (
	"encoding/json"
	"fmt"
	"os"
	"strings"
)

const pbsVERSION  = "1.0.0"

type Config struct {
	Port                  int                  `json:"Port"`
	ActiveProxyGroups     string               `json:"ActiveProxyGroups"`
	Proxies               map[string][]string  `json:"Proxies"`
	CheckEnabled          bool                 `json:"CheckEnabled"`
	CheckPingCount        int                  `json:"CheckPingCount"`
	CheckLossPercentage   float64              `json:"CheckLossPercentage"`
	CheckDuration         int                  `json:"CheckDuration"`
}

func processPBSArgs(args []string, configPath *string) {
	// no valid args
	if len(args) < 2 {
		usage()
	}

	// proceed by args
	switch args[1] {
	case "-h":
		usage()
	case "-c":
		getConfigFile(args, configPath)
	case "-v":
		version()
	default:
		usage()
	}
}

func usage() {
	fmt.Printf(`PBS %s - a proxy balancer that easy config and start

Usage: Config your pbs.json and start pbs with command ./pbs -c ./config.json &

Args:
	-c	Specify a config json
	-h	Help and quit
	-v	Show current version and quit

`, pbsVERSION)
	os.Exit(0)
}

func version() {
	fmt.Printf(`PBS - a proxy balancer that easy to config and start
Version: %s
`, pbsVERSION)
	os.Exit(0)
}

func getConfigFile(args []string, configPath *string){
	if len(args) < 3 {
		fmt.Println("Please specify config file path.")
		os.Exit(0)
	}

	// check config path input
	configFilePath := args[2]
	cFile, err := os.Stat(configFilePath)
	if err != nil {
		fmt.Printf("Config file is invalid: %s \n", err.Error())
		os.Exit(0)
	}

	// judge if file is a regular file
	if cFile.Mode().IsRegular() {
		*configPath = configFilePath
	} else {
		fmt.Println("Config file is invalid, maybe the path you specified is a directory?")
		os.Exit(0)
	}
}

func parseConfig(configPath *string, config *Config, proxiesArr *[]string) {
	// get File
	configFile, err := os.Open(*configPath)
	if err != nil {
		fmt.Printf("Config file failed to open: %s \n", err.Error())
		os.Exit(0)
	}
	defer func() {
		if err := configFile.Close(); err != nil {
			fmt.Printf("Config file failed to close: %s \n", err.Error())
			os.Exit(0)
		}
	}()
	fmt.Printf("Using config file: %s \n", *configPath)

	jsonParser := json.NewDecoder(configFile)
	if err := jsonParser.Decode(config); err != nil {
		fmt.Printf("Failed to parse config: %s \n", err.Error())
		os.Exit(0)
	}

	// parse proxies to an array
	ActiveGroupArr := strings.Split(config.ActiveProxyGroups, ",")
	for group, proxies := range config.Proxies {
		if config.ActiveProxyGroups == "all" || ContainsGroup(ActiveGroupArr, group) {
			*proxiesArr = append(*proxiesArr, proxies...)
		}
	}
	if len(*proxiesArr) == 0 {
		fmt.Println("Can not parse any proxies from config, please check if config is correct.")
		os.Exit(0)
	}
}

func ContainsGroup(s []string, e string) bool {
	for _, a := range s {
		if a == e {
			return true
		}
	}
	return false
}
